/**
 * Copyright (C) 2008 http://code.google.com/p/maven-license-plugin/
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.google.code.mojo.license.header;

import java.util.regex.Pattern;

/**
 * @author Cedric Pronzato
 */
public class HeaderDefinition
{
    private final String type;
    private String firstLine;
    private String beforeEachLine;
    private String endLine;

    private Pattern skipLinePattern;
    private Pattern firstLineDetectionPattern;
    private Pattern lastLineDetectionPattern;

    public HeaderDefinition(String type, String firstLine, String beforeEachLine, String endLine, String skipLinePattern, String firstLineDetectionPattern, String lastLineDetectionPattern)
    {
        this(type);
        this.firstLine = firstLine;
        this.beforeEachLine = beforeEachLine;
        this.endLine = endLine;
        this.skipLinePattern = compile(skipLinePattern);
        this.firstLineDetectionPattern = compile(firstLineDetectionPattern);
        this.lastLineDetectionPattern = compile(lastLineDetectionPattern);
    }

    public HeaderDefinition(String type)
    {
        this.type = type.toLowerCase();
    }

    private Pattern compile(String regexp)
    {
        return regexp == null ? null : Pattern.compile(regexp);
    }

    public String getFirstLine()
    {
        return firstLine;
    }

    public String getBeforeEachLine()
    {
        return beforeEachLine;
    }

    public String getEndLine()
    {
        return endLine;
    }

    public String getType()
    {
        return type;
    }

    public boolean mustSkip(String line)
    {
        return skipLinePattern != null && line != null && skipLinePattern.matcher(line).matches();
    }

    public boolean isFirstHeaderLine(String line)
    {
        return firstLineDetectionPattern != null && line != null && firstLineDetectionPattern.matcher(line).matches();
    }

    public boolean isLastHeaderLine(String line)
    {
        return lastLineDetectionPattern != null && line != null && lastLineDetectionPattern.matcher(line).matches();
    }

    protected Pattern getSkipLinePattern()
    {
        return skipLinePattern;
    }

    protected Pattern getFirstLineDetectionPattern()
    {
        return firstLineDetectionPattern;
    }

    protected Pattern getLastLineDetectionPattern()
    {
        return lastLineDetectionPattern;
    }

    public void setPropertyFromString(String property, String value)
    {
        if (isEmpty(value))
        {
            throw new IllegalArgumentException("The value cannot be empty for XML tag " + property + " for type " + type);
        }

        if ("firstLine".equalsIgnoreCase(property))
        {
            firstLine = value;
        }
        else if ("beforeEachLine".equalsIgnoreCase(property))
        {
            beforeEachLine = value;
        }
        else if ("endLine".equalsIgnoreCase(property))
        {
            endLine = value;
        }
        else if ("skipLine".equalsIgnoreCase(property))
        {
            skipLinePattern = compile(value);
        }
        else if ("firstLineDetectionPattern".equalsIgnoreCase(property))
        {
            firstLineDetectionPattern = compile(value);
        }
        else if ("lastLineDetectionPattern".equalsIgnoreCase(property))
        {
            lastLineDetectionPattern = compile(value);
        }
    }

    public void validate() {
        check("firstLine", this.firstLine);
        check("beforeEachLine", this.beforeEachLine);
        check("endLine", this.endLine);
        check("firstLineDetectionPattern", this.firstLineDetectionPattern);
        check("lastLineDetectionPattern", this.lastLineDetectionPattern);
        // skip line can be null
    }

    private void check(String name, String value) {
        if(isEmpty(value)) {
            throw new IllegalStateException(String.format("The property '%s' is missing for header definition '%s'", name, type));
        }
    }

    private void check(String name, Pattern value) {
        if(isEmpty(value.pattern())) {
            throw new IllegalStateException(String.format("The property '%s' is missing for header definition '%s'", name, type));
        }
    }

    private boolean isEmpty(String s) {
        return s == null || "".equals(s);
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        HeaderDefinition that = (HeaderDefinition) o;
        return !(type != null ? !type.equals(that.type) : that.type != null);
    }

    @Override
    public int hashCode() {
        return type != null ? type.hashCode() : 0;
    }

    @Override
    public String toString() {
        return type;
    }
}
